package james.gan.remoting.api;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import james.gan.common.Response;


public class RemotingFutureDispatchMonitor {

	private static final Map<String, Response> results = new ConcurrentHashMap<>();
	
	public RemotingFuture getResult(String requestId) {
		return new RemotingFuture(requestId);
	}

	public void setResult(Response response) {
		results.put(response.getId(), response);
	}

	public class RemotingFuture implements Future<Response> {

		String id;

		public RemotingFuture(String id) {
			this.id = id;
		}

		@Override
		public boolean cancel(boolean mayInterruptIfRunning) {
			return false;
		}

		@Override
		public boolean isCancelled() {
			return false;
		}

		@Override
		public boolean isDone() {
			return results.get(id) != null;
		}

		@Override
		public Response get() throws InterruptedException, ExecutionException {

			while (true) {
				if (isDone()) {
					return getAndRelease(id);
				}
			}
		}

		@Override
		public Response get(long timeout, TimeUnit unit)
				throws InterruptedException, ExecutionException, TimeoutException {
			long millis = unit.toMillis(timeout) + System.currentTimeMillis();
			while (System.currentTimeMillis() < millis) {
				if (isDone()) {
					return getAndRelease(id);
				}
			}
			return null;
		}

		private Response getAndRelease(String id) {
			Response response = results.get(id);
			results.remove(id);
			return response;
		}
	}
}
